// ServerSocketThread.cpp : implementation file
//

#include "stdafx.h"
#include "commserverlib.h"
#include "ServerSocketThread.h"
#include "ServerSocket.h"
#include "CommWithClient.h"

#include "CommonLib\Packet.h"
#include "CommonLib\Guard.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CServerSocketThread

IMPLEMENT_DYNCREATE(CServerSocketThread, CWinThread)

	CServerSocketThread::CServerSocketThread():
	m_hSocket(NULL)
{
	m_pSocket= new CServerSocket;
	m_bAutoDelete = FALSE;
	m_nLoginTime = 0;
}

CServerSocketThread::~CServerSocketThread()
{
	Guard guardIn(&m_mutexPacketsIn);
	Guard guardOut(&m_mutexPacketsOut);

	std::list<Packet*>::const_iterator iter;
	for (iter = m_PacketsIn.begin();iter != m_PacketsIn.end();++iter)
	{
		Packet * pPacket = *iter;
		delete pPacket;
	}
	m_PacketsIn.clear();

	for (iter = m_PacketsOut.begin();iter != m_PacketsOut.end();++iter)
	{
		Packet * pPacket = *iter;
		delete pPacket;
	}
	m_PacketsOut.clear();

	delete m_pSocket;
}

BOOL CServerSocketThread::InitInstance()
{
	// TODO:  perform and per-thread initialization here
	m_pSocket->Attach(m_hSocket);
	m_pSocket->Init();

	Guard guard(&CommWithClient::Instance()->m_mutexThreads);
	CommWithClient::Instance()->m_Threads.push_back(this);

	return TRUE;
}

int CServerSocketThread::ExitInstance()
{
	// TODO:  perform any per-thread cleanup here
	m_pSocket->Close();
	return CWinThread::ExitInstance();
}

BEGIN_MESSAGE_MAP(CServerSocketThread, CWinThread)
	//{{AFX_MSG_MAP(CServerSocketThread)
	// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
	ON_THREAD_MESSAGE(WM_APP_EXITSOCKETTHREAD, OnExitSocketThread)
	ON_THREAD_MESSAGE(WM_APP_SENDTO, OnSendTo)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CServerSocketThread message handlers

void CServerSocketThread::DeleteInstance()
{
	delete this;
}

LRESULT CServerSocketThread::OnExitSocketThread(WPARAM wParam, LPARAM lParam)
{
	m_pSocket->Close();
	PostQuitMessage(0);

	return 0;
}

LRESULT CServerSocketThread::OnSendTo(WPARAM wParam, LPARAM lParam)
{
	Packet * pPacket;

	do
	{
		pPacket = TakePacketToSend();
		if (pPacket)
		{
			m_pSocket->AsyncSend(pPacket);
			delete pPacket;
		}
	}
	while (pPacket);

	return 0;
}

Packet * CServerSocketThread::TakePacketToSend()
{
	Guard guard(&m_mutexPacketsOut);

	Packet * pPacket = NULL;

	if (m_PacketsOut.size() > 0)
	{
		std::list<Packet *>::iterator iter = m_PacketsOut.begin();
		pPacket = *iter;
		m_PacketsOut.erase(iter);
	}

	return pPacket;
}

Packet * CServerSocketThread::TakePacketReceived()
{
	Guard guard(&m_mutexPacketsIn);

	Packet * pPacket = NULL;

	if (m_PacketsIn.size() > 0)
	{
		std::list<Packet *>::iterator iter = m_PacketsIn.begin();
		pPacket = *iter;
		m_PacketsIn.erase(iter);
	}

	return pPacket;
}

void CServerSocketThread::AddPacketReceived(Packet * pPacket)
{
	Guard guard(&m_mutexPacketsIn);

	m_PacketsIn.push_back(pPacket);
	CommWithClient::Instance()->PostNotification(WM_APP_RECEIVED, (HANDLE)m_hSocket);
}

void CServerSocketThread::AddPacketToSend(Packet * pPacket)
{
	Guard guard(&m_mutexPacketsOut);

	m_PacketsOut.push_back(pPacket);
	PostThreadMessage(WM_APP_SENDTO, 0, 0);
}

bool CServerSocketThread::IsSocketHandleMatched(SOCKET hSocket) const
{
	return m_hSocket == hSocket;
}

void CServerSocketThread::SetbStop(bool bStop)
{
	m_pSocket->SetbStop( true);
}